#ifndef __FUZZY_H__
#define __FUZZY_H__

/* General-purpose fuzzy inference engine supporting any number of system
inputs and outputs, membership functions, and rules. Membership functions can
be any shape defineable by 2 points and 2 slopes--trapezoids, triangles,
rectanlges, etc. Rules can have any number of antecedents and outputs, and can
vary from rule to rule. "Min" method is used to compute rule strength, "Max"
for applying rule strengths, "Center-of-Gravity" for defuzzification. This
implementation of Inverted Pendulum control problem has: System Inputs, 2
(pendulum angle and velocity); System Outputs, 1 (force supplied to base of
pendulum); Membership Functions, 7 per system input/output; Rules, 15 (each
with 2 antecedents & 1 output). If more precision is required, integers can
be changed to real numbers.*/

#define MAXNAME 10          /* max number of characters in names           */
#define UPPER_LIMIT  100    /* max number assigned as degree of membership */

/* Membership functions are associated with each system input and output. */
typedef struct mf_type{
    char name[MAXNAME]; /* name of membership function (fuzzy set)    */
    double value;          /* degree of membership or output strength    */
    double point1;         /* leftmost x-axis point of mem. function     */
    double point2;         /* rightmost x-axis point of mem. function    */
    double slope1;         /* slope of left side of membership function  */
    double slope2;         /* slope of right side of membership function */
    struct mf_type *next;   /* pointer to next membership function    */
}f_mf_type;

/* io_type structure builds a list of system inputs and a list of system
outputs. After initialization, these lists are fixed, except for value field
which is updated on every inference pass. */
typedef struct io_type{
    char name[MAXNAME];        /*  name of system input/output       */
    double value;                 /*  value of system input/output      */
    f_mf_type *memf;           /*  list of membership functions for  */
                               /*     this system input/output       */
    struct io_type *next;      /*  pointer to next input/output      */
}f_io_type;

/* Each rule has an if side and a then side. Elements making up if side are
pointers to antecedent values inside mf_type structure. Elements making up then
side of rule are pointers to output strength values, also inside mf_type
structure. Each rule structure contains a pointer to next rule in rule base. */

typedef struct rule_element_type{
    double *value;                /* pointer to antecedent/output strength value */
    struct rule_element_type *next; /* next antecedent/output element in rule */
}f_rule_elemtype;

typedef struct rule_type{
    struct rule_element_type *if_side;     /* list of antecedents in rule */
    struct rule_element_type *then_side;   /* list of outputs in rule     */
    struct rule_type *next;                /* next rule in rule base      */
}f_rule_type;

void fuzzification(f_io_type *sysinput);
void rule_evaluation(f_rule_type *rulebase);
void defuzzification(f_io_type *sysoutput);
void fuzzy_refinement(f_rule_type *rulebase);

#endif /* __FUZZY_H__ */

